<template>
  <!-- 火狐浏览器需要加px -->
  <!--   连接线   -->
  <svg
    class="edge-svg"
    :class="{ 'line-highlight': highlight }"
    :style="{
      height: `${lineContainerHeight}px`,
      width: `${lineContainerWidth}px`,
      left: edge.x + 'px',
      top: edge.y + 'px',
    }"
  >
    <!-- line  -->
    <path
      :d="getPathD"
      class="line-cls"
      marker-end="url(#arrowhead)"
      :stroke-dasharray="lineStatus"
      :style="{
        'stroke-width':
          strokeWidth + (hoverLineStatus || highlight ? 1 : 0) + 'px',
        stroke: hoverLineStatus || highlight ? '#a8aeff' : '#b6bdd2',
        fill: 'none',
        'pointer-events': 'visiblestroke',
      }"
    />
    <!-- hover 线 透明 -->
    <path
      :d="getPathD"
      class="line-cls-hover"
      marker-end="url(#arrowhead)"
      :style="{
        'stroke-width': '10px',
        fill: 'none',
        'pointer-events': 'visiblestroke',
      }"
      @mousemove="mouseEventLine($event)"
      @mouseover="hoverEventLine()"
      @mouseleave="leaveEventLine()"
      @click="selectLine($event)"
      @contextmenu="connectLineContextmenu($event)"
    />
    <!-- 箭头 -->
    <path
      :d="getPathArrow"
      class="line-cls"
      :style="{
        'stroke-width':
          strokeWidth + (hoverLineStatus || highlight ? 1 : 0) + 'px',
        stroke: hoverLineStatus || highlight ? '#a8aeff' : '#b6bdd2',
      }"
    />
    <!-- 连线 添加节点按钮背景 -->
    <path
      v-show="addBtnStatus && !comparisonStatus && !isVisitor && !isLock"
      :d="addBtnPathBackground"
      class="add-btn"
      marker-end="url(#arrowhead)"
      :style="{ stroke: '#fff', fill: '#fff' }"
    />
    <!-- 连线 添加节点按钮 -->
    <path
      v-show="addBtnStatus && !comparisonStatus && !isVisitor && !isLock"
      :d="addBtnPath"
      class="add-btn"
      marker-end="url(#arrowhead)"
      :style="{ stroke: '#5964e4' }"
      @click="lineAddNode($event)"
      @mouseenter="hoverEventLine()"
      @mouseleave="leaveEventLine()"
      @contextmenu="connectLineContextmenu($event)"
    />
  </svg>
</template>

<script lang="ts">
/**
 * 关系连接线封装
 */
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import AddMenu from '@/components/studio/data/graph-compoments/AddMenu.vue'
import DataViewStore from '@/store/modules/dataview'

@Component({
  components: {
    AddMenu,
  },
})
export default class LineOfRelationalConnection extends Vue {
  // 连接线信息
  @Prop() edge!: any
  // 节点高度
  @Prop({ type: Number, default: 0 }) nodeHeight!: number
  // 节点宽度
  @Prop({ type: Number, default: 0 }) nodeWidth!: number
  // 差值宽
  @Prop({ type: Number, default: 0 }) differenceOfGridWidth!: number
  // 差值高
  @Prop({ type: Number, default: 0 }) differenceOfGridHeight!: number
  // 高亮
  @Prop({ type: Boolean, default: false }) highlight!: boolean
  // 连接线状态
  @Prop({ type: String, default: '' }) lineStatus!: string
  // 是否是访客
  @Prop({ type: Boolean, default: false }) isVisitor!: boolean
  // 项目是否锁定
  @Prop({ type: Boolean, default: false }) isLock!: boolean

  // 连接线 宽度
  public strokeWidth = 1
  // hover 连接线  click
  private hoverLineStatus: boolean = false
  // 添加按钮
  private addBtnStatus: boolean = false
  // 添加节点 按钮位置
  private addBtnPosition: any = { x: -100, y: -100 }

  // 可视化对比状态
  private get comparisonStatus() {
    return DataViewStore.comparisonStatus
  }

  // // 是否是访客
  // public get isVisitor() {
  //   return DataViewStore.isVisitor
  // }

  // public get isLock() {
  //   return DataViewStore.getLock
  // }

  @Watch('addBtnPosition', { deep: true })
  private btnPosition() {
    const position: any = {
      x: this.addBtnPosition.x - 7,
      y: this.addBtnPosition.y - 7,
    }
    // todo 连接线 按钮 改变位置的时候 $emit 事件  不应该在这里
    this.addBtnStatus = true
    this.$emit('menu-position', {
      position,
      edge: this.edge,
      btnStatus: this.addBtnStatus,
    })
  }

  // 路径的 4个位置点
  private PathPositionPoint: any = {
    point1: { x: 0, y: 0 },
    point2: { x: 0, y: 0 },
    point3: { x: 0, y: 0 },
    point4: { x: 0, y: 0 },
  }

  // 连接线 添加按钮
  public lineAddNode($event: MouseEvent) {
    $event.stopPropagation()
    const position: any = {
      x: this.addBtnPosition.x - 7,
      y: this.addBtnPosition.y - 7,
    }
    this.$emit('click-add-node', {
      position,
      edge: this.edge,
      btnStatus: this.addBtnStatus,
    })
  }

  /**
   * 连接线 svg  height,
   * 存一个 子节点 的 y 方向小于 父节点
   */
  public get lineContainerHeight() {
    // 父节点 y 方向大于 子节点
    if (this.edge.startEndPos) {
      return Math.abs(this.edge.startEndPos.yStart - this.edge.startEndPos.yEnd)
    }
    return Math.abs(this.edge.startEndPos.yEnd - this.edge.startEndPos.yStart)
  }

  /**
   * 连接线 svg  width
   */
  public get lineContainerWidth() {
    return Math.abs(this.edge.startEndPos.xEnd - this.edge.startEndPos.xStart)
  }

  private get addBtnPathBackground() {
    return `
      M ${this.addBtnPosition.x}, ${this.addBtnPosition.y}
      m -9, 0
      a 9,9 0 1,0 18,0
      a 9,9 0 1,0 -18,0
    `
  }

  // 添加按钮
  private get addBtnPath() {
    return `
      M ${this.addBtnPosition.x}, ${this.addBtnPosition.y}
      m -7, 0
      a 7,7 0 1,0 14,0
      a 7,7 0 1,0 -14,0
      M${this.addBtnPosition.x},${this.addBtnPosition.y - 4}
      L${this.addBtnPosition.x},${this.addBtnPosition.y + 4}
      M${this.addBtnPosition.x - 4},${this.addBtnPosition.y}
      L${this.addBtnPosition.x + 4},${this.addBtnPosition.y}
    `
  }

  public connectLineContextmenu($event: MouseEvent) {
    $event.preventDefault()
    this.$emit('edit-line', {
      positionX: $event.offsetX + this.edge.x,
      positionY: $event.offsetY + this.edge.y,
      edge: this.edge,
    })
  }

  /**
   * 连接线 路径
   */
  public get getPathD() {
    // yStatus 为 true 父节点 y 方向 在子节点下方
    const { yStatus, rowEqual } = this.edge.startEndPos
    const startPos = {
      x: this.edge.startEndPos.xStart,
      y:
        this.edge.startEndPos.yStart +
        (yStatus ? (-1 / 2) * this.nodeHeight : (1 / 2) * this.nodeHeight),
    }
    const endPos = {
      x: this.edge.startEndPos.xEnd,
      y:
        this.edge.startEndPos.yEnd -
        (yStatus ? (-1 / 2) * this.nodeHeight : (1 / 2) * this.nodeHeight),
    }
    // 连接线四个点
    const point1 = {
      x: endPos.x - this.differenceOfGridWidth - 5,
      y: startPos.y,
    }
    const point2 = {
      x: endPos.x - this.differenceOfGridWidth,
      y: startPos.y + (yStatus ? -5 : 5),
    }
    const point3 = {
      x: endPos.x - this.differenceOfGridWidth,
      y: endPos.y + (yStatus ? 5 : -5),
    }
    const point4 = { x: endPos.x - this.differenceOfGridWidth + 5, y: endPos.y }

    this.PathPositionPoint = { point1, point2, point3, point4 }

    if (rowEqual) {
      return `M${startPos.x},${startPos.y} L${endPos.x},${endPos.y}`
    }
    return `
      M${startPos.x},${startPos.y}
      L${point1.x},${point1.y}
      A 5 5 0 0, ${yStatus ? 0 : 1} ${point2.x} ${point2.y}
      L${point3.x}, ${point3.y}
      A 5 5 0 0, ${yStatus ? 1 : 0} ${point4.x} ${point4.y}
      L${endPos.x},${endPos.y}
     `
  }

  /**
   * 连接线 箭头
   */
  private get getPathArrow() {
    const { yStatus } = this.edge.startEndPos
    const endPos = {
      x: this.edge.startEndPos.xEnd,
      y:
        this.edge.startEndPos.yEnd -
        (yStatus ? (-1 / 2) * this.nodeHeight : (1 / 2) * this.nodeHeight),
    }
    return `
    M${endPos.x},${endPos.y}
    L${endPos.x - 5},${endPos.y - 5}
    M${endPos.x},${endPos.y}
    L${endPos.x - 5},${endPos.y + 5}
  `
  }

  /**
   * hover 连接线 添加按钮
   */
  public hoverEventLine() {
    this.hoverLineStatus = true
    this.addBtnStatus = true
  }

  /**
   * mouseEnter 连接线
   * @param $event
   */
  private mouseEventLine($event: MouseEvent) {
    const { offsetX } = $event
    const { yStatus, rowEqual } = this.edge.startEndPos
    if (rowEqual) {
      this.addBtnPosition.x =
        (this.edge.startEndPos.xEnd - this.edge.startEndPos.xStart) / 2
      this.addBtnPosition.y = (1 / 2) * this.nodeHeight
    } else {
      const leftOrRight = offsetX < this.PathPositionPoint.point2.x
      if (leftOrRight) {
        this.addBtnPosition.x = this.PathPositionPoint.point2.x / 2
        this.addBtnPosition.y = yStatus
          ? this.lineContainerHeight - (1 / 2) * this.nodeHeight
          : (1 / 2) * this.nodeHeight
      } else {
        this.addBtnPosition.x =
          this.PathPositionPoint.point4.x +
          (1 / 2) * this.differenceOfGridWidth -
          5
        this.addBtnPosition.y = yStatus
          ? (1 / 2) * this.nodeHeight
          : this.lineContainerHeight - (1 / 2) * this.nodeHeight
      }
    }
  }

  /**
   * leave 连接线 添加按钮
   */
  public leaveEventLine() {
    this.hoverLineStatus = false
    this.addBtnStatus = false
    // TODO lineTodo1
    // const position: any = {x: this.addBtnPosition.x - 7, y: this.addBtnPosition.y - 7}
    // this.$emit('menu-position', {position, edge: this.edge, btnStatus: this.addBtnStatus})
  }

  /**
   * 选择 连接线
   * @param $event
   */
  public selectLine($event: MouseEvent) {
    $event.stopPropagation()
    this.$emit('active-line', this.edge)
  }
}
</script>

<style scoped lang="less">
/* 连接线 */
.edge-svg {
  pointer-events: none;
  position: absolute;
  z-index: 40;
  /*transition-duration: 0.2s, 0.2s, 0.2s, 0.2s;*/
  /*transition-property: width, height, left, top;*/
  &:hover {
    z-index: 50;
  }

  .line-cls {
    fill: none;
    stroke: #9b9da8;
  }

  .line-cls-hover {
    cursor: pointer;
    fill: none;
    stroke: transparent;
  }

  .add-btn {
    cursor: pointer;
    fill: transparent;
  }

  path {
    pointer-events: all;
    /*transition: all 0.2s;*/
  }
}

.line-highlight {
  z-index: 45;
}
</style>
